/* NOGRAPH.C */

/*
	Copyright (C) 2010 by Lesnikov Andrey <ozkriff@gmail.com>
	This file is part of ozkriff_game_2.

	ozkriff_game_2 is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	ozkriff_game_2 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with ozkriff_game_2.  If not, see <http://www.gnu.org/licenses/>.

	See the COPYING file for more details.
*/

#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include "SDL/SDL.h"
#include "SDL/SDL_ttf.h"
#include "SDL/SDL_opengl.h"
#include "SDL/SDL_net.h"

#include "defines.h"
#include "nograph.h"
#include "path.h"


extern ushort	back_path_x[100];
extern ushort	back_path_y[100];
extern ushort	back_path_current;
extern bool	CAN_GET_THERE[MAP_SIZE_X][MAP_SIZE_Y];


unittype UNIT_TYPES[] = 
{
//	NORMAL-0; ROAD-1; FOREST-2; WATER-3; HILLS-4; MOUNT-5;
//	see	morale	health	dist	attack	defence	move	name	terrain			terain defence
	{3,	5,	5,	3,	3,	2,	4,	"arch",	{2, 1, 4, 8, 4, 8},	{0, 0, 2, -2, 3, 3}},
	{2,	5,	5,	1,	6,	4,	4,	"atck",	{2, 1, 4, 8, 4, 8},	{0, 0, 3, -3, 3, 3}},
	{1,	5,	10,	1,	4,	6,	3,	"def",	{2, 1, 4, 8, 4, 8},	{0, 0, 3, -4, 4, 3}},
	{4,	5,	4,	1,	4,	4,	6,	"hunt",	{2, 1, 2, 4, 3, 4},	{0, 0, 5, 0,  4, 4}},
};

TCPsocket SOCKET;
SDLNet_SocketSet SOCKET_SET;

uint8_t NET_MODE = MODE_PASSIVE;

int MODE = MODE_SELECT;
int PREVIOUS_MODE;

int FIGHT_MODE;

fight FIGHT = {NULL, NULL, 0};

uint PLAYER;

uint aX = 99,  aY = 99; //active cell
unit* SELECTED_UNIT = NULL;

//инфа о сторонах шестигранника.
float HEX_EX;
float HEX_IN;
float HEX[6*3]; //хранит координаты вершин шестригранника

cell MAP[MAP_SIZE_X][MAP_SIZE_Y]; //собсственно это и есть карта =)

bool IS_PROGRAM_LOOPING = true;

move MOVE;

unit* UNITS; // список с юнитами

char *SERVER = "localhost";

//======================================================



void
send_to_server(uint8_t u)
{
	SDLNet_TCP_Send(SOCKET, &u, 1);
}

void
recv_from_server(uint8_t *u)
{
	SDLNet_TCP_Recv(SOCKET, u, 1);
}

uint
get_distance(int x1, int y1, int x2, int y2)
{
	x1 += y1/2;
	x2 += y2/2;
	
	int dx = x2 - x1;
	int dy = y2 - y1;
	
	return((abs(dx) + abs(dy) + abs(dx-dy)) / 2);
}



bool
get_close_hex_pos(ushort x, ushort y, int id, ushort *dest_x, ushort *dest_y)
{
	ushort dx, dy;

	if(y%2 == 0)
		switch (id)
		{
			case 0:
				dx = x+1;
				dy = y-1;
				break;
			case 1:
				dx = x+1;
				dy = y;  
				break;
			case 2:
				dx = x+1;
				dy = y+1;
				break;
			case 3:
				dx = x;
				dy = y+1;
				break;
			case 4:
				dx = x-1;
				dy = y;  
				break;
			case 5:
				dx = x;
				dy = y-1;
				break;
		}
	else
		switch (id)
		{
			case 0:
				dx = x;
				dy = y-1;
				break;
			case 1:
				dx = x+1;
				dy = y;  
				break;
			case 2:
				dx = x;
				dy = y+1;
				break;
			case 3:
				dx = x-1;
				dy = y+1;
				break;
			case 4:
				dx = x-1;
				dy = y;  
				break;
			case 5:
				dx = x-1;
				dy = y-1;
				break;
		}
	
	if ((dx < MAP_SIZE_X) && (dy < MAP_SIZE_Y))
	{
		*dest_x = dx;
		*dest_y = dy;
		return(true);
	}
	
	return(false);
}



// преобразовывает координаты сетки в реальные
void
map_to_real(int mx, int my, float *rx, float *ry)
{
	*rx = (2 * HEX_IN * mx);
	if (my%2 != 0)
		*rx -= HEX_IN;
	*ry = 1.5 * HEX_EX * (float)my;
}



void
generate_hex()
{
	HEX_EX = 0.42;
	//HEX_EX = 1;
	HEX_IN = sqrt(HEX_EX*HEX_EX - (HEX_EX/2)*(HEX_EX/2));
	
	int i;
	//for(i = 5; i >= 0; i--)
	for (i=0; i<6; i++) {
		HEX[i*3]   = HEX_EX * cos((M_PI_2) + 2*M_PI * i/6);  //x
		HEX[i*3+1] = HEX_EX * sin((M_PI_2) + 2*M_PI * i/6);  //y
		HEX[i*3+2] = 0; //пропустить Z элемент
	}
}



bool
is_lines_cross(float x1, float y1, float x2, float y2,
	       float x3, float y3, float x4, float y4)
{
	float ua = ((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))
		   /((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1));
	float ub = ((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))
		   /((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1));
//	printf("ua:%f, ub:%f\n", ua, ub);

//TODO как то странно подсвечивает граничные хексы
//	if(0<ua && ua<1 && 0<ub && ub <1){     //НЕ учитывать общие вершины
	if (0<=ua && ua<=1 && 0<=ub && ub <=1) { //   учитывать общие вершины
		//printf("point is (%.2f, %.2f)\n", x1+ua*(x2-x1), y1+ua*(y2-y1));
		return(true);
	} else {
		//puts("no point");
		return(false);
	}
}



bool
check_line_hex_intersects(
	int bx, int by, // begin
	int ex, int ey, // end
	int cx, int cy  // check it
)
{
	float rbx, rby; // begin
	float rex, rey; // end
	float rcx, rcy; // check it
	bool intersects = false;
	
	int i;
	for (i = 0; i < 3; i++) {
		map_to_real(cx, cy, &rcx, &rcy);
		
		float x1 = rcx + HEX_EX * cos((M_PI_2) + 2*M_PI * i/6);
		float y1 = rcy + HEX_EX * sin((M_PI_2) + 2*M_PI * i/6);
		
		float x2 = rcx + HEX_EX * cos((M_PI_2) + 2*M_PI * (i+3)/6);
		float y2 = rcy + HEX_EX * sin((M_PI_2) + 2*M_PI * (i+3)/6);
		
		map_to_real(bx, by, &rbx, &rby);
		map_to_real(ex, ey, &rex, &rey);
		
		if (is_lines_cross(x1,y1,x2,y2,   rbx,rby,rex,rey)) {
			intersects = true;
		}
	}
	
	return((bool)intersects);
}



float
get_rot_angle(int x1, int y1, int x2, int y2)
{
	float rx1, ry1, rx2, ry2;
	map_to_real(x1, y1, &rx1, &ry1);
	map_to_real(x2, y2, &rx2, &ry2);
	
	float distance = sqrt(pow(ry2-ry1, 2) + pow(rx2-rx1, 2));
	float angle = (asin((rx2-rx1)/distance))/ M_PI * 180.0;
	
	if (ry2-ry1 > 0)
		angle = -(180+angle);
		
	return(angle);
}



//TODO встроить в movelogic
void
start_move(int x1, int y1, int x2, int y2)
{
	map_to_real(x1, y1, &MOVE.rx1, &MOVE.ry1);
	map_to_real(x2, y2, &MOVE.rx2, &MOVE.ry2);
	
	float speed = MOVE.unit->movement_speed;
	float distance = sqrt(pow(MOVE.ry2-MOVE.ry1, 2) + pow(MOVE.rx2-MOVE.rx1, 2));
	
	MOVE.step_x = speed * ((MOVE.rx2-MOVE.rx1)/distance);
	MOVE.step_y = speed * ((MOVE.ry2-MOVE.ry1)/distance);
	MOVE.step_count = (int)(distance/speed);
}





void
check_win()
{
	int p1=0, p2=0;
	unit* t = UNITS;
	while(t)
	{
		if (t->player == 1) p1++;
		if (t->player == 2) p2++;
		t = t->next;
	}
	if(!p1)
	{
		puts("PLAYER 2 WIN");
		//exit(0);
		IS_PROGRAM_LOOPING = false;
	}
	if(!p2)
	{
		puts("PLAYER 1 WIN");
		//exit(0);
		IS_PROGRAM_LOOPING = false;
	}
}



void
end_player_turn()
{
	if(NET_MODE != MODE_ACTIVE)
		return;
		
	//change_button_text_by_name ("who_active", "ход противник");
		
	puts("deactivated. passive mode.");
	send_to_server(NET_T_MODE);
	
	NET_MODE = MODE_PASSIVE;

	SELECTED_UNIT = false;
	
	check_win();
}



void
calculate_damage()
{
	float c1 = (float)FIGHT.u1->health/FIGHT.u1->type->health;
	float c2 = (float)FIGHT.u2->health/FIGHT.u2->type->health;
	int attack  = FIGHT.u1->attack * c1;
	//int defence = FIGHT.u2->defence * c2;
	int defence = FIGHT.u2->defence * c2 + FIGHT.u2->type->ter_def[MAP[FIGHT.u2->mx][FIGHT.u2->my].type];

	if(defence < attack)
		FIGHT.damage = attack - defence;
	else
		FIGHT.damage = 1;

	printf("> hel(%i,%i), cof(%.2f,%.2f), nom(%i,%i), mod(%i,%i), DMG:%i\n",
		FIGHT.u1->health, FIGHT.u2->health,
		c1, c2,
		FIGHT.u1->attack, FIGHT.u2->defence,
		attack, defence, FIGHT.damage);
}



bool
add_unit (int x, int y, int player, unittype *type)
{
	unit* u = malloc(sizeof(unit));
	if (u == NULL)
		return(false);
		//exit(1);

	//добавит юнита в список
	u->next = UNITS;
	UNITS = u; //теперь список будет начинаться с него
	
	map_to_real(x, y, &(u->x), &(u->y)); //реальные координаты юнита
	u->mx = x;
	u->my = y;
	u->player = player;
	u->rot = (rand()%6)*60+30; // потоврот персонажа. 30, 90, т.д.
	u->frame = (rand()%22)+99; //рандомный кадр из idle анимации
	u->ap = type->ap;
	//u->cost_attack = type->cost_attack;
	u->rotation_speed = 5;
	u->movement_speed = 0.031; // просто подобрал
	u->health = type->health;
	u->attack_distance = type->attack_distance;
	u->morale = type->morale;
	u->attack = type->attack;
	u->defence = type->defence;

	u->type = type;
	 
	//запомнить, что он находится в этой клетке
	MAP[x][y].unit = u;
	
	if(u->player == PLAYER)
		update_fog(u->type->see, u->mx, u->my, +1);
	
	return(true);
}



void
init_map()
{
	int y, x;

//NORMAL 0 N n
//ROAD   1 R r
//FOREST 2 F f
//WATER	 3 W w
//HILLS	 4 H h
//MOUNT  5 M m

	uint tmp_map[MAP_SIZE_X][MAP_SIZE_Y] = 
	{
		 {0,0,0,1,1,1,1,0},
		{2,2,0,2,2,1,2,1},
		 {0,0,0,0,1,1,1,0},
		{3,3,3,0,1,1,0,0},
		 {0,0,0,0,1,3,3,3},
		{0,0,0,0,0,1,0,0},
		 {0,3,3,0,0,0,0,0},
		{0,0,3,0,0,0,0,0},
	};
	
	for (y=0; y<MAP_SIZE_Y; y++)
	{
		for (x=0; x<MAP_SIZE_X; x++)
		{ 
			MAP[x][y].unit = NULL;
			MAP[x][y].move_cost = 30000;
			//MAP[x][y].type = tmp_map[y][x];
			MAP[x][y].type = 0;
			MAP[x][y].fog = 0;
		}
	}

	//for(x = 0; x < 8; x++)
	//add_unit(x, 0, 1, 1);
	
	add_unit(4, 4, 1, &UNIT_TYPES[0]);
	add_unit(5, 4, 1, &UNIT_TYPES[0]);
	add_unit(6, 4, 1, &UNIT_TYPES[0]);
	add_unit(7, 4, 1, &UNIT_TYPES[0]);

	add_unit(0, 6, 1, &UNIT_TYPES[0]);
	add_unit(1, 6, 1, &UNIT_TYPES[1]);
	add_unit(2, 6, 1, &UNIT_TYPES[2]);
	//add_unit(3, 6, 1, &UNIT_TYPES[3]);

	add_unit(0, 1, 2, &UNIT_TYPES[0]);
	add_unit(1, 1, 2, &UNIT_TYPES[1]);
	add_unit(2, 1, 2, &UNIT_TYPES[2]);
	add_unit(3, 1, 2, &UNIT_TYPES[3]);
}



void
move_logic_rotate() //хрень. надо перераспределеить функционал
{
	// точки пути перечислены в обратном порядке
	float a = get_rot_angle(
			  back_path_x[back_path_current-1],
			  back_path_y[back_path_current-1],
			  back_path_x[back_path_current-2],
			  back_path_y[back_path_current-2]);
 
	while (a - MOVE.unit->rot > +180) a -= 360;
	while (a - MOVE.unit->rot < -180) a += 360;
	float diff = a - MOVE.unit->rot;
	
	if (abs(diff) < 6) { //мы достигли нужной точности
		MOVE.unit->rot = a; //доворачиваем юнит на нужный угол
		back_path_current--;
		start_move(back_path_x[back_path_current],
			   back_path_y[back_path_current],
			   back_path_x[back_path_current-1],
			   back_path_y[back_path_current-1]);
			   
		if(MOVE.unit->player == PLAYER)
		{
			update_fog(MOVE.unit->type->see, back_path_x[back_path_current], back_path_y[back_path_current], -1);
			update_fog(MOVE.unit->type->see, back_path_x[back_path_current-1], back_path_y[back_path_current-1], +1);
		}
		
		//MOVE.unit->mx = back_path_x[back_path_current];
		//MOVE.unit->my = back_path_y[back_path_current];
		// нужно для плавного появления юнитов из тумана войны
		MOVE.unit->mx = back_path_x[back_path_current-1];
		MOVE.unit->my = back_path_y[back_path_current-1];
		
		//update_fog(MOVE.unit->type->see, MOVE.unit->mx, MOVE.unit->my, +1);

		MAP[MOVE.unit->mx][MOVE.unit->my].unit = NULL;
	} else { //rotate it
		if (diff > 0)
			MOVE.unit->rot += 5;
		else
			MOVE.unit->rot -= 5;
	}
}


void
move_logic()
{
	if (MODE != MODE_MOVE)
		return;

	if (MOVE.step_count > 0) // we have not reached the destination
	{
		MOVE.unit->x += MOVE.step_x;
		MOVE.unit->y += MOVE.step_y;
		MOVE.step_count--;
	}
	else
	{
		if (back_path_current > 1) //если еще точки в маршруте
		{
			move_logic_rotate(); //повернуться к новой цели
		}
		else // end of movement    //закончить движение
		{ 
			MODE = MODE_SELECT;
			map_to_real(back_path_x[0], back_path_y[0], &(MOVE.unit->x), &(MOVE.unit->y));
			MOVE.unit->mx = back_path_x[0];
			MOVE.unit->my = back_path_y[0];
			MOVE.unit->frame = 98; //перейти к анимации ничегонеделания
			MAP[MOVE.unit->mx][MOVE.unit->my].unit = MOVE.unit;
			//fill_map(MOVE.unit); //перезаполнить карту под новую позицию
			if(SELECTED_UNIT) fill_map(SELECTED_UNIT);
			MOVE.unit = NULL; //никто больше не передвигается, так же?
		}
	}
}




bool
atack_logic_rotate()
{
	float a1 = get_rot_angle( FIGHT.u1->mx, FIGHT.u1->my,
			FIGHT.u2->mx, FIGHT.u2->my);
	float a2 = a1 - 180; //второго солдата надо повернуть наоборот
	
	while (a1 - FIGHT.u1->rot > 180) a1 -= 360;
	while (a1 - FIGHT.u1->rot < -180)a1 += 360;
	float diff1 = a1 - FIGHT.u1->rot;
	
	while (a2 - FIGHT.u2->rot > 180) a2 -= 360;
	while (a2 - FIGHT.u2->rot < -180)a2 += 360;
	float diff2 = a2 - FIGHT.u2->rot;
	
	if (abs(diff1) > 6) {
		if (diff1 > 0)
			FIGHT.u1->rot += 5;
		else
			FIGHT.u1->rot -= 5;
	}
	if (abs(diff2) > 6) {
		if (diff2 > 0)
			FIGHT.u2->rot += 5;
		else
			FIGHT.u2->rot -= 5;
	}
	//TODO нужно вынести поворот в отдельную функцию
	
	if (abs(diff1) > 6 || abs(diff2) > 6)
		return(false);
	else
		return(true);
}



void
atack_logic()
{
	if (MODE != MODE_FIGHT)
		return;

	if(!atack_logic_rotate())
		return;

	if (FIGHT.u1->frame < 25 || FIGHT.u1->frame > 48)
		FIGHT.u1->frame = 25;
		
	//TODO переделать всю систем боевой анимции
	if (FIGHT.u2->health > FIGHT.damage) //выдержит он удар или нет
	{
		if (FIGHT.u2->frame < 48 || FIGHT.u2->frame > 72) //анимацию защиты
			FIGHT.u2->frame = 48;
	}
	else
	{
		if (FIGHT.u2->frame < 72 || FIGHT.u2->frame > 96) //анимацию смерти
			FIGHT.u2->frame = 72;
	}
	
	// если был сыгран последний кадр. ТО...
	if (FIGHT.u1->frame == 48)
	{
		if(FIGHT.u2->health > FIGHT.damage)
		{
			// если он выжил
			FIGHT.u2->health -= FIGHT.damage;
			FIGHT.u2->morale -= FIGHT.damage;
			FIGHT.u2->frame = 97;

			FIGHT.u1->morale += 1;
			if(FIGHT.u1->morale == FIGHT.u1->type->morale)
			{
				FIGHT.u1->morale = FIGHT.u1->type->morale;
			}

			// контратака
			uint distance = get_distance(FIGHT.u1->mx, FIGHT.u1->my, FIGHT.u2->mx, FIGHT.u2->my);
			if(FIGHT_MODE == MODE_FIGHT_1 && distance <= FIGHT.u2->type->attack_distance)
			{
				if(FIGHT.u2->morale > 3)
				{
					unit *u = FIGHT.u1;
					FIGHT.u1 = FIGHT.u2;
					FIGHT.u2 = u;
					FIGHT_MODE = MODE_FIGHT_2;

					calculate_damage();

					return;
				}
			}

#if(0)
			//отступление
			if(FIGHT_MODE == MODE_FIGHT_2 || distance > FIGHT.u2->type->attack_distance)
			{
				unit *a, *d;
				a = FIGHT.u2;
				d = FIGHT.u1;

				ushort x, y, direction = ((int)(d->rot-25))/60;
				get_close_hex_pos(a->mx, a->my, direction, &x, &y);
				fill_map(a);
				if (MAP[x][y].move_cost <= a->type->ap && CAN_GET_THERE[x][y]) 
				{
					MODE = MODE_MOVE;
					MOVE.step_count = 0;
					MOVE.unit = a;
					get_path(a, x, y);
					MAP[MOVE.unit->mx][MOVE.unit->my].unit = NULL;
				}
				else
				{
					MODE = MODE_SELECT;
					a->frame = 97; // вернуть к анимации ничегонеделания
				}
				a->frame = 97; // вернуть к анимации ничегонеделания

				return;
			}
#endif
		}
		else
		{
			unit* tmp = UNITS;
			if(tmp == FIGHT.u2) //если надо удал перв элем-т списка
			{
				UNITS = UNITS->next; //меняем ук-ль на нач списка
			}
			else //иначе 
			{
				while(tmp->next != FIGHT.u2)
					tmp = tmp->next;
				tmp->next = FIGHT.u2->next;
			}
			MAP[FIGHT.u2->mx][FIGHT.u2->my].unit = NULL;
			free(FIGHT.u2);
			fill_map(FIGHT.u1);
		}

		MODE = MODE_SELECT;
		FIGHT.u1->frame = 97; // вернуть к анимации ничегонеделания

		check_win();
	}
}



void
change_frames()
{
	if (MODE == MODE_PAUSE)
		return;

	unit* tmp = UNITS;
	while(tmp != NULL)
	{
		if (tmp != MOVE.unit)
			if (tmp->frame++ == 120) //анимация ничегонеделания.
				tmp->frame = 97;
		if (tmp == MOVE.unit)
			if (tmp->frame++ > 22) //анимация передвижения
				tmp->frame = 1;
		tmp = tmp->next;
	}
}



void
init_net()
{
	SDLNet_Init();
	
	IPaddress ip;
	
	//char *SERVER = "192.168.0.1";
	SDLNet_ResolveHost(&ip, SERVER, 2000);

	SOCKET = SDLNet_TCP_Open(&ip);
	if(!SOCKET)
	{
		puts("cannot open socket");
		exit(1);
	}

	SOCKET_SET = SDLNet_AllocSocketSet(1);
	SDLNet_TCP_AddSocket(SOCKET_SET, SOCKET);
	
	send_to_server((uint8_t)PLAYER);
}


void
do_net()
{
	if(NET_MODE != MODE_PASSIVE)		return;
	if(MODE != MODE_SELECT)			return;
	if(!SDLNet_CheckSockets(SOCKET_SET, 0)) return;
	if(!SDLNet_SocketReady(SOCKET))		return;

	uint8_t m;
	recv_from_server(&m);

	switch(m)
	{
		default: break;

		case NET_T_MODE:
		{
			//puts("I AM ACTIVE NOW!!");
			puts("activated.");
			//change_button_text_by_name ("who_active", "ВАШ ход");
			
			NET_MODE = MODE_ACTIVE;
			
			unit* tmp = UNITS;
			while(tmp != NULL)
			{
				if (tmp->player == PLAYER)
				{
					tmp->can_atack = true;
					tmp->ap = tmp->type->ap;
				}
				tmp = tmp->next;
			}
			
			break;
		}

		case NET_MOVE:
		{
			uint8_t id, x1, y1, x2, y2;
			recv_from_server(&id);
			recv_from_server(&x1);
			recv_from_server(&y1);
			recv_from_server(&x2);
			recv_from_server(&y2);
			
			printf("MOVE (%u) ", id);
			printf("(%u;",  (unsigned int) x1);
			printf("%u)->", (unsigned int) y1);
			printf("(%u;",  (unsigned int) x2);
			printf("%u)\n", (unsigned int) y2);
			
			//MAP[x1][y1].unit->ap -= MAP[x2][y2].move_cost;
			MAP[x1][y1].unit->ap = 0;
			MODE = MODE_MOVE;
			MOVE.step_count = 0;
			MOVE.unit = MAP[x1][y1].unit;
			fill_map(MOVE.unit);
			get_path(MOVE.unit, x2, y2);
			MAP[x1][y1].unit = NULL;
			
			break;
		}
		
		case NET_FIGHT:
		{
			uint8_t id, x1, y1, x2, y2;
			recv_from_server(&id);
			recv_from_server(&x1);
			recv_from_server(&y1);
			recv_from_server(&x2);
			recv_from_server(&y2);
			
			printf("FIGHT (%u) ", id);
			printf("(%u;",  (unsigned int) x1);
			printf("%u)->", (unsigned int) y1);
			printf("(%u;",  (unsigned int) x2);
			printf("%u)\n", (unsigned int) y2);
			
			MAP[x1][y1].unit->can_atack = false;
			FIGHT.u1 = MAP[x1][y1].unit;
			FIGHT.u2 = MAP[x2][y2].unit;
			MODE = MODE_FIGHT;
			FIGHT_MODE = MODE_FIGHT_1;

			calculate_damage();
			
			break;
		}
		
		case NET_CH_TERRAIN:
		{
			//puts("changin terrain");
			
			uint8_t x, y;
			recv_from_server(&x);
			recv_from_server(&y);
			MAP[x][y].type++;
			if(MAP[x][y].type > 3)
				MAP[x][y].type = 0;
			break;
		}

		case NET_QUIT:
		{
			puts("recived NET_QUIT signal.");
			IS_PROGRAM_LOOPING = false;

			break;
		}
	}

}


void
do_logic()
{
	move_logic();
	atack_logic();
}



void
update_fog(ushort see, ushort ux, ushort uy, int value)
{
	ushort x, y;
	
	for (x=0; x<MAP_SIZE_X; x++)
		for (y=0; y<MAP_SIZE_Y; y++)
			if(get_distance(ux, uy, x, y) <= see)
			//if(get_distance(ux, uy, x, y) <= 1)
				MAP[x][y].fog += value;
}


